#include "GaugeCloud.h"

#include <QPainter>
#include <QConicalGradient>
#include <QMouseEvent>
#include <QResizeEvent>
#include <QtMath>
#include <QDebug>

/**
 * @brief 构造函数
 * @param parent 父窗口指针
 */
GaugeCloud::GaugeCloud(QWidget *parent)
    : QWidget(parent)
    , m_repeatTimer(this)
{
    // 初始化默认值
    initDefaults();

    // 设置鼠标跟踪
    setMouseTracking(true);

    // 配置自动重复定时器
    m_repeatTimer.setInterval(m_autoRepeatInterval);
    connect(&m_repeatTimer, &QTimer::timeout, this, &GaugeCloud::onRepeatTimerTimeout);

    // 设置默认风格
    m_style = CloudStyle_White;
}

/**
 * @brief 初始化默认值
 */
void GaugeCloud::initDefaults()
{
    // 位置名称列表（顺序：0=底部,1=左下角,2=左侧,3=左上角,4=顶部,5=右上角,6=右侧,7=右下角,8=中间）
    m_positions = QStringList() << "底部" << "左下角" << "左侧" << "左上角"
                                << "顶部" << "右上角" << "右侧" << "右下角" << "中间";

    // 清空图标数据
    m_directionPixmaps.clear();
    m_directionPaths.clear();

    // 初始化灰白色调颜色
    initColorsForStyle(CloudStyle_White);

    // 默认中心路径（圆形图标）
    QPainterPath p;
    p.addEllipse(QRectF(-10, -10, 20, 20));
    QPainterPath dot;
    dot.addEllipse(QRectF(-4, -4, 8, 8));
    m_centerPath = p.united(dot);
}

/**
 * @brief 根据风格初始化颜色
 * @param s 风格枚举值（仅CloudStyle_White有效）
 */
void GaugeCloud::initColorsForStyle(CloudStyle s)
{
    Q_UNUSED(s);

    // 增强对比度的灰白色调方案

    // 1. 背景颜色
    m_bgColor = QColor(248, 248, 248);

    // 2. 边框颜色
    m_borderColor1 = QColor(245, 245, 245);
    m_borderColor2 = QColor(232, 232, 232);
    m_borderColor3 = QColor(218, 218, 218);
    m_borderColor4 = QColor(245, 245, 245);

    // 3. 图标颜色 - 增强对比度
    m_textColor = QColor(90, 90, 90);     // 普通状态：中等灰色
    m_enterColor = QColor(50, 50, 50);    // hover状态：明显变暗
    m_pressColor = QColor(20, 20, 20);    // press状态：接近黑色，强烈反馈

    // 4. 中心区域颜色 - 增强对比度
    m_centerBorderColor = QColor(200, 200, 200); // 中心边框
    m_centerBgColor = QColor(250, 250, 250);    // 中心背景（普通状态：很浅）
    m_centerHoverColor = QColor(220, 220, 220); // 中心背景（hover状态：明显变暗）
    m_centerPressColor = QColor(180, 180, 180); // 中心背景（press状态：更暗，强烈反馈）
}

/**
 * @brief 绘制事件处理
 * @param ev 绘制事件
 */
void GaugeCloud::paintEvent(QPaintEvent *ev)
{
    Q_UNUSED(ev);

    int w = width();
    int h = height();
    int side = qMin(w, h);

    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    // 坐标系变换到内部单位 -100..100
    painter.translate(w / 2.0, h / 2.0);
    painter.scale(side / 200.0, side / 200.0);

    // 绘制所有组件
    paintBackground(painter);   // 绘制外盘和背景
    paintInnerCircle(painter);  // 绘制中心区域
    paintIcons(painter);        // 绘制8个方向图标
}

/**
 * @brief 绘制背景
 * @param p 绘图器
 */
void GaugeCloud::paintBackground(QPainter &p)
{
    // 1. 绘制内层背景（带渐变）
    if (m_gradient) {
        QConicalGradient gr(0, 0, 0);
        gr.setColorAt(0.0, m_borderColor1);
        gr.setColorAt(0.4, m_borderColor2);
        gr.setColorAt(0.7, m_borderColor3);
        gr.setColorAt(1.0, m_borderColor4);

        p.save();
        p.setPen(Qt::NoPen);
        p.setBrush(gr);
        p.drawEllipse(QPointF(0,0), 99 - m_margin, 99 - m_margin);

        // 内层浅灰背景
        p.setBrush(m_bgColor);
        p.drawEllipse(QPointF(0,0), 90 - m_margin, 90 - m_margin);
        p.restore();
    }
    // 2. 简单模式（无渐变）
    else {
        p.save();
        p.setPen(Qt::NoPen);
        p.setBrush(m_borderColor1);
        p.drawEllipse(QPointF(0,0), 99 - m_margin, 99 - m_margin);

        // 边框（深灰色）
        p.setBrush(Qt::NoBrush);
        QPen pen(m_borderColor2);
        pen.setWidthF(6.0);
        p.setPen(pen);
        p.drawArc(QRectF(-91 + m_margin, -91 + m_margin, 182 - 2*m_margin, 182 - 2*m_margin), 30*16, 120*16);

        // 内层背景
        p.setBrush(m_bgColor);
        p.drawEllipse(QPointF(0,0), 83 - m_margin, 83 - m_margin);
        p.restore();
    }
}

/**
 * @brief 绘制中心区域
 * @param p 绘图器
 */
void GaugeCloud::paintInnerCircle(QPainter &p)
{
    const double centerSize = 30.0;
    double outer = centerSize + m_centerBorderWidth - m_margin;

    p.save();

    // 1. 中心区域边框（根据状态变化，增强对比度）
    QColor borderColor = m_inCenter ?
                             (m_pressed ? QColor(150, 150, 150) : QColor(180, 180, 180)) :
                             m_centerBorderColor;

    // 2. 中心区域背景（根据状态变化，增强对比度）
    QColor bgColor = m_inCenter ?
                         (m_pressed ? m_centerPressColor : m_centerHoverColor) :
                         m_centerBgColor;

    // 绘制边框
    p.setPen(Qt::NoPen);
    p.setBrush(borderColor);
    p.drawEllipse(QPointF(0,0), outer, outer);

    // 绘制背景
    p.setBrush(bgColor);
    p.drawEllipse(QPointF(0,0), centerSize - m_margin, centerSize - m_margin);

    // 在按下状态添加内阴影效果，增强点击感
    if (m_inCenter && m_pressed) {
        p.setBrush(QColor(0, 0, 0, 30));
        p.drawEllipse(QPointF(0,0), centerSize - m_margin - 2, centerSize - m_margin - 2);
    }

    p.restore();
}

/**
 * @brief 绘制图标
 * @param p 绘图器
 */
void GaugeCloud::paintIcons(QPainter &p)
{
    p.save();

    // 1. 中心图标
    if (!m_centerPixmap.isNull()) {
        QPixmap pm = m_centerPixmap.scaled(48, 48, Qt::KeepAspectRatio, Qt::SmoothTransformation);

        // 在按下状态添加透明度效果
        if (m_inCenter && m_pressed) {
            p.setOpacity(0.7);
        }
        p.drawPixmap(QPointF(-pm.width()/2.0, -pm.height()/2.0), pm);
        p.setOpacity(1.0);
    } else {
        p.setPen(Qt::NoPen);
        // 中心图标颜色根据状态变化
        QColor centerIconColor = m_inCenter ?
                                     (m_pressed ? QColor(60, 60, 60) : QColor(100, 100, 100)) :
                                     m_textColor;
        p.setBrush(centerIconColor);
        p.drawPath(m_centerPath);
    }

    // 2. 八方向图标 - 增强点击效果
    const int steps = 8;
    const double radius = 72.0 - m_margin;
    const double dotRadius = 8.0;

    for (int i = 0; i < steps; ++i) {
        double thetaDeg = 90.0 + i * 45.0;
        double thetaRad = qDegreesToRadians(thetaDeg);
        double cx = radius * std::cos(thetaRad);
        double cy = radius * std::sin(thetaRad);

        p.save();
        p.translate(cx, cy);

        // 检查是否有自定义图标
        if (i < m_directionPixmaps.size() && !m_directionPixmaps[i].isNull()) {
            QPixmap pm = m_directionPixmaps[i].scaled(24, 24, Qt::KeepAspectRatio, Qt::SmoothTransformation);

            // 在按下状态添加透明度效果
            if (!m_inCenter && m_position == i && m_pressed) {
                p.setOpacity(0.7);
            }
            p.drawPixmap(QPointF(-pm.width()/2.0, -pm.height()/2.0), pm);
            p.setOpacity(1.0);
        }
        // 使用默认圆形图标
        else {
            bool isHot = (!m_inCenter && m_position == i && (m_enter || m_pressed));
            QColor col = isHot ?
                             (m_pressed ? m_pressColor : m_enterColor) :
                             m_textColor;

            p.setBrush(col);
            p.setPen(Qt::NoPen);

            // 在按下状态稍微放大图标，增强点击感
            double currentRadius = dotRadius;
            if (!m_inCenter && m_position == i && m_pressed) {
                currentRadius = dotRadius * 1.2;
            }

            p.drawEllipse(QPointF(0,0), currentRadius, currentRadius);

            // 在悬停状态添加光环效果
            if (!m_inCenter && m_position == i && m_enter && !m_pressed) {
                p.setBrush(QColor(200, 200, 200, 80));
                p.drawEllipse(QPointF(0,0), currentRadius + 3, currentRadius + 3);
            }
        }
        p.restore();
    }

    p.restore();
}

/**
 * @brief 检测点击位置
 * @param localPos 本地坐标
 * @return 位置索引（-1=无点击,0-7=方向,8=中心）
 */
int GaugeCloud::hitTestLocal(const QPoint &localPos) const
{
    // 计算内部坐标系中的位置
    QPointF pixelCenter = widgetCenter();
    int side = qMin(width(), height());
    double scale = side / 200.0;

    QPointF internal;
    internal.setX( (localPos.x() - pixelCenter.x()) / scale );
    internal.setY( (localPos.y() - pixelCenter.y()) / scale );

    // 1. 检查是否在中心区域
    const double centerRadius = 30.0 - m_margin;
    double dCenter = std::hypot(internal.x(), internal.y());
    if (dCenter <= centerRadius) return 8;

    // 2. 检查是否在外部环形区域
    const double outerLimit = 100.0 - m_margin;
    if (dCenter > outerLimit) return -1;

    // 3. 检查八方向图标
    const int steps = 8;
    const double iconRadiusPos = 72.0 - m_margin;
    const double iconHitRadius = 14.0;

    for (int i = 0; i < steps; ++i) {
        double thetaDeg = 90.0 + i * 45.0;
        double thetaRad = qDegreesToRadians(thetaDeg);
        double cx = iconRadiusPos * std::cos(thetaRad);
        double cy = iconRadiusPos * std::sin(thetaRad);
        double d = std::hypot(internal.x() - cx, internal.y() - cy);
        if (d <= iconHitRadius) return i;
    }

    return -1;
}

/**
 * @brief 鼠标按下事件处理
 * @param ev 鼠标按下事件
 */
void GaugeCloud::mousePressEvent(QMouseEvent *ev)
{
    m_pressed = true;
    m_lastPoint = ev->pos();
    int idx = hitTestLocal(ev->pos());
    if (idx >= 0) m_position = idx;
    m_inCenter = (m_position == 8);
    update();
    QString name = (m_position >=0 && m_position < m_positions.size()) ? m_positions.at(m_position) : QString();
    emit mousePressed(m_position, name);
    if (m_autoRepeat) {
        QTimer::singleShot(m_autoRepeatDelay, this, [this]() {
            if (this->m_pressed) this->m_repeatTimer.start();
        });
    }
}

/**
 * @brief 鼠标释放事件处理
 * @param ev 鼠标释放事件
 */
void GaugeCloud::mouseReleaseEvent(QMouseEvent *ev)
{
    Q_UNUSED(ev);
    m_repeatTimer.stop();
    m_pressed = false;
    m_inCenter = false;
    update();
    QString name = (m_position >=0 && m_position < m_positions.size()) ? m_positions.at(m_position) : QString();
    emit mouseReleased(m_position, name);
}

/**
 * @brief 鼠标移动事件处理
 * @param ev 鼠标移动事件
 */
void GaugeCloud::mouseMoveEvent(QMouseEvent *ev)
{
    m_lastPoint = ev->pos();
    int idx = hitTestLocal(ev->pos());
    if (idx != -1 && idx != m_position) {
        m_position = idx;
        QString name = (m_position >=0 && m_position < m_positions.size()) ? m_positions.at(m_position) : QString();
        emit positionChanged(m_position, name);
    }
    m_inCenter = (m_position == 8);
    update();
}

/**
 * @brief 鼠标进入事件处理
 * @param ev 鼠标进入事件
 */
void GaugeCloud::enterEvent(QEvent *ev)
{
    Q_UNUSED(ev);
    m_enter = true;
    update();
}

/**
 * @brief 鼠标离开事件处理
 * @param ev 鼠标离开事件
 */
void GaugeCloud::leaveEvent(QEvent *ev)
{
    Q_UNUSED(ev);
    m_enter = false;
    update();
}

/**
 * @brief 大小调整事件处理
 * @param ev 大小调整事件
 */
void GaugeCloud::resizeEvent(QResizeEvent *ev)
{
    QWidget::resizeEvent(ev);
    update();
}

/**
 * @brief 自动重复定时器超时处理
 */
void GaugeCloud::onRepeatTimerTimeout()
{
    if (!m_pressed) {
        m_repeatTimer.stop();
        return;
    }
    QString name = (m_position >=0 && m_position < m_positions.size()) ? m_positions.at(m_position) : QString();
    emit mousePressed(m_position, name);
}

/**
 * @brief 获取控件中心点
 * @return 控件中心点坐标
 */
QPointF GaugeCloud::widgetCenter() const
{
    return QPointF(width() / 2.0, height() / 2.0);
}

/**
 * @brief 计算两点间距离
 * @param a 点A
 * @param b 点B
 * @return 两点间欧氏距离
 */
double GaugeCloud::twoPtDistance(const QPointF &a, const QPointF &b) const
{
    double dx = a.x() - b.x();
    double dy = a.y() - b.y();
    return std::hypot(dx, dy);
}
